package com.zzg.mybatis.generator.plugins;

import org.mybatis.generator.api.CommentGenerator;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.java.*;
import org.mybatis.generator.api.dom.xml.XmlElement;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;
import java.util.Set;

import static org.mybatis.generator.internal.util.StringUtility.isTrue;

/**
 * 此插件使用数据库表中列的注释来生成Java Model中属性的注释
 *
 * @author Owen Zou
 * 
 */
public class DbRemarksCommentGenerator implements CommentGenerator{

	private Properties properties;
	
	private boolean columnRemarks;
	
	private boolean isAnnotations;
	
	public DbRemarksCommentGenerator(){
        super();
        properties = new Properties();
    }
	
	@Override
	public void addClassAnnotation(InnerClass innerClass,IntrospectedTable introspectedTable,Set<FullyQualifiedJavaType> set){
		
	}

	@Override
	public void addClassComment(InnerClass innerClass,IntrospectedTable introspectedTable){
		
	}

	@Override
	public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable,boolean arg2){
		innerClass.addJavaDocLine("/**"); //$NON-NLS-1$
        innerClass.addJavaDocLine(" */"); //$NON-NLS-1$
	}

	@Override
	public void addComment(XmlElement xmlElement){
		
	}

	@Override
	public void addConfigurationProperties(Properties properties){
		this.properties.putAll(properties);
        columnRemarks = isTrue(properties.getProperty("columnRemarks"));
        isAnnotations = isTrue(properties.getProperty("annotations"));
	}

	@Override
	public void addEnumComment(InnerEnum innerEnum,IntrospectedTable introspectedTable){
		
	}

	@Override
	public void addFieldAnnotation(Field field,IntrospectedTable introspectedTable,Set<FullyQualifiedJavaType> set){
		
	}

	@Override
	public void addFieldAnnotation(Field field,IntrospectedTable introspectedTable,IntrospectedColumn arg2,Set<FullyQualifiedJavaType> set){
		
	}

	@Override
	public void addFieldComment(Field field,IntrospectedTable introspectedTable){
		if(columnRemarks){
			StringBuilder sb = new StringBuilder();
	        field.addJavaDocLine("/**");
	        sb.append(" * ");
	        sb.append(introspectedTable.getFullyQualifiedTable());
	        field.addJavaDocLine(sb.toString());
	        field.addJavaDocLine(" */");
		}
	}

	@Override
	public void addFieldComment(Field field,IntrospectedTable introspectedTable,IntrospectedColumn introspectedColumn){
		if(columnRemarks){
            field.addJavaDocLine("/** "+ introspectedColumn.getRemarks()+" */");
		}
        if(isAnnotations){
            boolean isId = false;
            for(IntrospectedColumn column:introspectedTable.getPrimaryKeyColumns()){
                if(introspectedColumn == column){
                    isId = true;
                    field.addAnnotation("@Id");
                    field.addAnnotation("@GeneratedValue");
                    break;
                }
            }
            if(!introspectedColumn.isNullable() && !isId){
                field.addAnnotation("@NotEmpty");
            }
            if(introspectedColumn.isIdentity()){
                if(introspectedTable.getTableConfiguration().getGeneratedKey().getRuntimeSqlStatement().equals("JDBC")){
                    field.addAnnotation("@GeneratedValue(generator = \"JDBC\")");
                }else{
                    field.addAnnotation("@GeneratedValue(strategy = GenerationType.IDENTITY)");
                }
            }else if(introspectedColumn.isSequenceColumn()){
                field.addAnnotation("@SequenceGenerator(name=\"\",sequenceName=\"" + introspectedTable.getTableConfiguration().getGeneratedKey().getRuntimeSqlStatement() + "\")");
            }
        }
	}

	@Override
	public void addGeneralMethodAnnotation(Method method,IntrospectedTable introspectedTable,Set<FullyQualifiedJavaType> set){
		
	}

	@Override
	public void addGeneralMethodAnnotation(Method method,IntrospectedTable introspectedTable,IntrospectedColumn introspectedColumn,Set<FullyQualifiedJavaType> set){
		
	}

	@Override
	public void addGeneralMethodComment(Method method,IntrospectedTable introspectedTable){
		
	}

	@Override
	public void addGetterComment(Method method,IntrospectedTable introspectedTable,IntrospectedColumn introspectedColumn){
		
	}

	@Override
	public void addJavaFileComment(CompilationUnit compilationUnit){
		if (isAnnotations) {
            compilationUnit.addImportedType(new FullyQualifiedJavaType("javax.persistence.Table"));
            compilationUnit.addImportedType(new FullyQualifiedJavaType("javax.persistence.Id"));
            compilationUnit.addImportedType(new FullyQualifiedJavaType("javax.persistence.Column"));
            compilationUnit.addImportedType(new FullyQualifiedJavaType("javax.persistence.GeneratedValue"));
            compilationUnit.addImportedType(new FullyQualifiedJavaType("org.hibernate.validator.constraints.NotEmpty"));
        }
	}

	@Override
	public void addModelClassComment(TopLevelClass topLevelClass,IntrospectedTable introspectedTable){
		topLevelClass.addJavaDocLine("/**");
        topLevelClass.addJavaDocLine(" * @数表名称 " + introspectedTable.getFullyQualifiedTable()+"("+introspectedTable.getRemarks()+")");
        topLevelClass.addJavaDocLine(" * @开发日期 " + new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
        topLevelClass.addJavaDocLine(" */");
        if(isAnnotations){
            topLevelClass.addAnnotation("@Table(name=\"" + introspectedTable.getFullyQualifiedTableNameAtRuntime() + "\")");
        }
        //添加private static final long serialVersionUID = 1L;
        Field field = new Field();
        field.setFinal(true);
        field.setInitializationString("1L");
        field.setName("serialVersionUID");
        field.setStatic(true);
        field.setType(new FullyQualifiedJavaType("long"));
        field.setVisibility(JavaVisibility.PRIVATE);
        topLevelClass.addField(field);
	}

	@Override
	public void addRootComment(XmlElement xmlElement){
		
	}

	@Override
	public void addSetterComment(Method method,IntrospectedTable introspectedTable,IntrospectedColumn introspectedColumn){
		
	}
}